package com.example.demo.randomTest;

import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;

/**
 * @author FF998
 */
public class RandomController {
    public static void main(String[] args) {

//        // 随机获取集合内字符串
//        List<String> nameList = Arrays.asList("南京", "黑龙江", "长春", "沈阳", "呼和浩特", "北京", "天津", "石家庄", "济南", "太原", "西安",
//                "兰州", "乌鲁木齐", "西宁", "拉萨", "成都", "郑州", "合肥", "武汉", "重庆", "贵阳", "长沙", "南昌", "上海", "杭州", "福州", "昆明", "南宁", "广州", "海口", "苏州", "青岛");
//        // 打乱列表
//        Collections.shuffle(nameList);
//        // 取前十个元素
//        List<String> randomNames = nameList.subList(0, 10);
//        randomNames.forEach(System.out::println);

        for (int i = 0; i < 10; i++) {
            // 生成指定范围的随机double数字
            double v = getDoubleNumber(7, true, 9, true);
            System.out.println(v);

            // 获取指定范围内的整型随机数
//            int integerNumber = getIntegerNumber(1, true, 1000, true);
//            System.out.println(integerNumber);

//            Random random = new Random();
//            System.out.println(random.nextInt(3)-1);


        }
    }

    /**
     * 生成指定范围的随机double数字
     *
     * @param min      最小值
     * @param minReach 最小值是否可以取到（true-可以）
     * @param max      最大值
     * @param maxReach 最大值是否可以取到（true-可以）
     * @return 符合要求的随机数
     */
    public static double getDoubleNumber(double min, boolean minReach, double max, boolean maxReach) {
        double num;
        if (minReach) {
            if (maxReach) {
                // todo 虽然涉及循环，但是目前没有找到不降低取值密度的写法
                // 使用取余数之类带整型的写法，基本都会降低取值密度
                do {
                    // 该公式的取值范围是：[min, max + 0.001)
                    num = ThreadLocalRandom.current().nextDouble(min, max + 0.001);
                }
                // 排除掉取值大于max的情况，剩下的就是符合要求的值了
                while (num > max);
            } else { // [min, max)
                // 方式一
                // num = min + Math.random() * (max - min);
                // 方式二
                num = ThreadLocalRandom.current().nextDouble(min, max);
            }
        } else {
            if (maxReach) {
                num = max - Math.random() * (max - min);
            } else {
                /**
                 * 解释：
                 * (max - 1 - Math.random() * (max - min - 1)) ∈ (min, max - 1]
                 * Math.random() ∈ [0, 1)
                 * 两者相加，可知最终结果取值范围就是 (min, max)
                 * 注意，不要尝试使用乘法结合律
                 */
                num = Math.random() + (max - 1 - Math.random() * (max - min - 1));
            }
        }
        DecimalFormat decimalFormat = new DecimalFormat("#.00");
        return Double.parseDouble(decimalFormat.format(num));
    }

    /**
     * 获取指定范围内的整型随机数
     *
     * @param min      最小值
     * @param minReach 是否取到最小值
     * @param max      最大值
     * @param maxReach 是否取到最大值
     * @return 符合要求的随机整型数字
     */
    public static int getIntegerNumber(Integer min, boolean minReach, Integer max, boolean maxReach) {
        int num;
        Random rand = new Random();
        if (minReach) {
            // [min, max]
            if (maxReach) {
                // 方式一
                // num = min + rand.nextInt(max - min + 1);
                // 方式二
                num = ThreadLocalRandom.current().nextInt(min, max + 1);
            } else { // [min, max)
                // num = min + rand.nextInt(max - min);  // 方式一
                num = ThreadLocalRandom.current().nextInt(min, max); // 方式二
            }
        } else {
            // (min, max]
            if (maxReach) {
                num = max - rand.nextInt(max - min);
            } else { // (min, max) = [min + 1, max)
                num = min + 1 + rand.nextInt(max - min - 1);
            }
        }
        return num;
    }
}
